// 数组类型注解
let arr1:Array<number>=[1,2,3]
let arr2: number[] = [1, 2, 3]
//联合类型
let arr3: (string | number)[] = [18, 'jack']
//类型别名
type ItemType = (string | number)[]
let arr4: ItemType = ['jack', 100]
//函数类型
function add(a: number, b: number): number { 
    return a+b
}
//函数表达式(分开注解)
const add1 = (a: number, b: number): number => {
    return a+b
}
//函数表达式(整体注解)
type AddFn = (a: number, b: number) => number
const add2: AddFn = (a, b) => { 
    return a+b
}
// 可选参数
function buildName(firstName: string, lastName?: string) {
    if (lastName) {
        return `${firstName}${lastName}`
    } else { 
        return firstName
    }
}
//无返回值
function eachArr(arr: number[]): void { 
    arr.forEach((item) => {
        console.log(item)
     })
}

// 接口类型
interface Person { 
    name: string,
    age: number,
    sex?:string
}
// 接口继承
interface singlePerson extends Person { 
    isHaveFriends:boolean
}



// 类型别名交叉类型实现继承
type Person2 = {
    name: string,
    age: number,
    sex?:string
}
type allPerson2 = Person2 & {
   isHaveFriends:boolean
}


//接口类型和类型别名的区别
// 相同点

// 1. 都能描述对象类型
// 2. 都能实现继承，interface使用extends, type配合交叉类型

// 不同点

// 1. type除了能描述对象还可以用来自定义其他类型
// 2. 同名的interface会合并（属性取并集，不能出现类型冲突），同名type会报错

// 在注解对象类型的场景下非常相似，推荐大家一律使用type, type更加灵活


// 字面量类型
//any类型
//类型断言 语法: 变量 as 类型

//泛型
//泛型：就是指在类定义时不会设置类中的属性或方法参数的具体类型，
// 而是在类使用时（创建对象）再进行类型的定义。会在编译期检查类型是否错误。
// 1.泛型接口 interface ResData<T> { }
// 2.泛型别名 type ResData<T>= { }
// 3.泛型函数 function fn<T>() { }
// 4.泛型约束-------------------------------不懂

// 例:
// 定义泛型
interface ResData<T> { 
    msg: string,
    code: number,
    data:T
}
//定义具体类型
interface User { 
    name: string,
    age:number
}
//使用泛型并传入具体类型
let userData: ResData<User>= { 
    code: 200,
    msg: 'success',
    data: {
        name: 'jack',
        age:18
    }
}